import os
import json
import uuid
import requests
from fastapi import FastAPI, Request, Response
from openai import OpenAI

app = FastAPI()


@app.post("/webhook")
async def handle_webhook(request: Request):
    try:
        body = await request.json()
    except Exception as e:
        print(f"No payload found: {str(e)}")
        return Response(content="No payload found.", status_code=400)

    label = body.get('label')
    page_created = body.get('page')
    webhook_type = None
    article_id = None

    if label and (label.get('labels') or label.get('name')):
        webhook_type = "LABEL_ADDED"
    elif page_created and page_created.get('id'):
        webhook_type = "PAGE_CREATED"

    if webhook_type == "LABEL_ADDED":
        print(f"Received LABEL_ADDED webhook.", label)
        annotate_label = os.environ.get("OMNIVORE_ANNOTATE_LABEL", False)

        if not annotate_label:
            print("No label specified in environment.")
            return Response(content="No label specified in environment.", status_code=400)

        labels = label.get('labels') or [label]
        label_names = [l.get('name') for l in labels]

        if annotate_label not in label_names:
            print(
                f"Label '{annotate_label}' does not match any of the labels '{label_names}' specified in environment.",
                label)
            return Response(content="Not an annotation label", status_code=400)

        article_id = label['pageId']

    elif webhook_type == "PAGE_CREATED":
        print(f"Received PAGE_CREATED webhook.", page_created)
        article_id = page_created['id']

    else:
        print("Neither label data received nor PAGE_CREATED event.")
        return Response(content="Neither label data received nor PAGE_CREATED event.", status_code=400)

    # STEP 1: Fetch the full article content from Omnivore
    omnivore_headers = {
        "Content-Type": "application/json",
        "Authorization": os.environ["OMNIVORE_API_KEY"]
    }

    query = f"""
    query Article {{
        article(
            slug: "{article_id}"
            username: "."
            format: "markdown"
        ) {{
            ... on ArticleSuccess {{
                article {{
                    title
                    content
                    labels {{
                        name
                    }}
                }}
            }}
        }}
    }}
    """

    try:
        omnivore_response = requests.post(
            "https://api-prod.omnivore.app/api/graphql",
            headers=omnivore_headers,
            json={"query": query}
        )
        omnivore_response.raise_for_status()
        omnivore_data = omnivore_response.json()
        article_content = omnivore_data['data']['article']['article']['content']
        article_title = omnivore_data['data']['article']['article']['title']
    except Exception as error:
        return Response(content=f"Error fetching article from Omnivore: {str(error)}", status_code=500)

    # STEP 2: Generate a completion using OpenAI's API
    openai_client = OpenAI()  # assumes OPENAI_API_KEY is set in environment
    prompt = os.environ.get("OPENAI_PROMPT", "Return a tweet-length TL;DR of the following article.")
    model = os.environ.get("OPENAI_MODEL", "gpt-3.5-turbo-16k")
    settings = json.loads(os.environ.get("OPENAI_SETTINGS", f'{{"model":"{model}"}}'))

    try:
        completion_response = openai_client.chat.completions.create(
            **settings,
            messages=[
                {
                    "role": "user",
                    "content": f"Instruction: {prompt}\nArticle content: {article_content}"
                }
            ]
        )
        print(
            f'Fetched completion from OpenAI for article "{article_title}" (ID: {article_id}) using prompt "{prompt}": {json.dumps(completion_response.usage.model_dump())}')
    except Exception as error:
        return Response(
            content=f'Error fetching completion from OpenAI for article "{article_title}" (ID: {article_id}) using prompt "{prompt}": {str(error)}',
            status_code=500)

    article_annotation = completion_response.choices[0].message.content.strip().replace('"', '\\"').replace('\\',
                                                                                                            '\\\\')

    # STEP 3: Update Omnivore article with OpenAI completion
    highlight_id = str(uuid.uuid4())
    short_id = highlight_id[:8]

    mutation = {
        "query": """
        mutation CreateHighlight($input: CreateHighlightInput!) {
            createHighlight(input: $input) {
                ... on CreateHighlightSuccess {
                    highlight {
                        ...HighlightFields
                    }
                }
                ... on CreateHighlightError {
                    errorCodes
                }
            }
        }

        fragment HighlightFields on Highlight {
            id
            type
            shortId
            quote
            prefix
            suffix
            patch
            color
            annotation
            createdByMe
            createdAt
            updatedAt
            sharedAt
            highlightPositionPercent
            highlightPositionAnchorIndex
            labels {
                id
                name
                color
                createdAt
            }
        }
        """,
        "variables": {
            "input": {
                "type": "NOTE",
                "id": highlight_id,
                "shortId": short_id,
                "articleId": article_id,
                "annotation": article_annotation
            }
        }
    }

    try:
        omnivore_annotation_response = requests.post(
            "https://api-prod.omnivore.app/api/graphql",
            headers=omnivore_headers,
            json=mutation
        )
        omnivore_annotation_response.raise_for_status()
        response_data = omnivore_annotation_response.json()
        print(
            f'Article annotation added to article "{article_title}" (ID: {article_id}): {json.dumps(response_data["data"]["createHighlight"])}')
        print(f'Used this GraphQL query: {json.dumps(mutation)}')
        return Response(content="Article annotation added.")
    except Exception as error:
        return Response(
            content=f'Error adding annotation to Omnivore article "{article_title}" (ID: {article_id}): {str(error)}',
            status_code=500)


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8000)